package com.tbit.main.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.tbit.common.constant.OperationPlatform;
import com.tbit.common.entity.MachineOpLog;
import com.tbit.main.constant.DaoParamConstant;
import com.tbit.main.constant.FaultTypeConstant;
import com.tbit.main.constant.MachineFaultConstant;
import com.tbit.main.controller.interceptor.LoginUserContextHolder;
import com.tbit.main.dao.log.MachineFaultLogDao;
import com.tbit.main.exception.BaseException;
import com.tbit.main.pojo.*;
import com.tbit.main.service.*;
import com.tbit.main.util.StringUtil;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 故障记录日志表
 *
 * @author LMY
 * @create 2022-11-17 13:26
 */
@Service
public class MachineFaultLogServiceImpl implements MachineFaultLogService {

    @Autowired
    private MachineFaultLogDao machineFaultLogDao;
    @Autowired
    private RoleService roleService;
    @Autowired
    private GeoreGionService georeGionService;
    @Autowired
    private AccountUserService accountUserService;
    @Autowired
    private DataService dataService;
    @Autowired
    private UserService userService;
    @Autowired
    private AccountService accountService;
    @Autowired
    private MachineOpLogService machineOpLogService;

    @Override
    public void insert(MachineFaultLog machineFaultLog) {
        machineFaultLogDao.insert(machineFaultLog);

        AccountUser accountUser = LoginUserContextHolder.getLoginUser();
        Machine machine = dataService.getMachine(machineFaultLog.getMachineId());

        // 插入车辆操作日志
        machineOpLogService.insertSingle(MachineOpLog.builder()
                .accountId(machineFaultLog.getAccountId())
                .machineId(machineFaultLog.getMachineId())
                .machineNO(machine.getMachineNO())
                .userCode(machineFaultLog.getUserCode())
                .operation("故障申报")
                .opUser(Objects.isNull(accountUser) ? machineFaultLog.getAddManName() : accountUser.getName())
                .opUserPhone(Objects.isNull(accountUser) ? machineFaultLog.getAddManPhone() : accountUser.getPhone())
                .opPlatform(OperationPlatform.MAINTAIN.code)
                .result(true)
                .opTime(LocalDateTime.now())
                .build()
        );

    }

    @Override
    public List<MachineFaultLogSta> groupByTime(Integer agentId, Integer userType, Integer addManId, Integer faultType,
                                                String startTime, String endTime, List<Integer> regionId, Integer machineType) {
        List<MachineFaultLogSta> dlses;

        /**查询代理商运维账号*/
        List<Integer> accountUserIds = new ArrayList<>();
        /**判断当前账号是不是运维人员*/
        if (roleService.getRoleCode(userType).equals(1)) {
            accountUserIds.add(addManId);
        }

        Map<String, Object> params = new HashMap<>();
        params.put(DaoParamConstant.accountId, agentId);
        params.put("addManIds", StringUtil.getListString(accountUserIds));
        params.put("faultType", faultType);
        params.put(DaoParamConstant.startTime, startTime);
        params.put(DaoParamConstant.endTime, endTime);
        if (CollectionUtils.isEmpty(regionId)) {
            params.put("exist", "'exist'");
            regionId = georeGionService.getByAccountUserId(addManId);
        } else {
            params.put("exist", null);
        }
        params.put("regionId", StringUtil.getListString(regionId));
        params.put("machineType", machineType);
        params.put("intoMain", MachineFaultConstant.FAULT_MAIN);
        dlses = machineFaultLogDao.groupByTime(params);
        List<Integer> accountUserIdList = dlses.stream().map(MachineFaultLogSta::getAddManId).collect(Collectors.toList());
        Map<Integer, AccountUser> accountUserMap = accountUserService.getByIds(accountUserIdList)
                .stream().collect(Collectors.toMap(AccountUser::getAccountUserId, Function.identity()));
        dlses.forEach(d -> {
            Optional<AccountUser> accountUserOptional =  Optional.ofNullable(accountUserMap.get(d.getAddManId()));
            d.setName(accountUserOptional.map(AccountUser::getName).orElse("-"));
            d.setPhone(accountUserOptional.map(AccountUser::getPhone).orElse("-"));
            d.setDelFlag(accountUserOptional.map(AccountUser::getDelFlag).orElse(1));
        });
        return dlses;
    }

    @Override
    public List<MachineFaultLog> getByTime(Integer accountId, Integer addManId, Integer faultType, String startTime, String endTime,
                                           String userCode, List<Integer> regionId, Integer machineType) {
        Map<String, Object> params = new HashMap<>();
        params.put(DaoParamConstant.accountId, accountId);
        params.put("addManId", addManId);
        params.put("faultType", faultType);
        params.put(DaoParamConstant.startTime, startTime);
        params.put(DaoParamConstant.endTime, endTime);
        if (CollUtil.isEmpty(regionId)) {
            params.put("exist", "'exist'");
            regionId = georeGionService.getByAccountUserId(addManId);
        } else {
            params.put("exist", null);
        }
        params.put("regionId", StringUtil.getListString(regionId));
        params.put("machineType", machineType);
        params.put("intoMain", MachineFaultConstant.FAULT_MAIN);
        params.put("userCode", userCode);
        return machineFaultLogDao.getByTime(params);
    }

    @Override
    public List<MachineFaultLog> getByNO(String orderNO) {
        List<MachineFaultLog> machineFaultLogs = machineFaultLogDao.getByNO(orderNO);

        List<Integer> dlsesPhone = machineFaultLogs.stream().filter(d -> Objects.isNull(d.getAddManName())).map(MachineFaultLog::getAddManId).collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(dlsesPhone)) {
            List<Integer> accountUserIds = machineFaultLogs.stream().map(MachineFaultLog::getAddManId).collect(Collectors.toList());
            List<AccountUser> accountUsers = accountUserService.getByIds(accountUserIds);
            Map<Integer, AccountUser> accountUserMap = new HashMap<>();
            for (AccountUser accountUser : accountUsers) {
                accountUserMap.put(accountUser.getAccountUserId(), accountUser);
            }
            machineFaultLogs.stream().forEach(m -> {
                m.setAddManName(Optional.ofNullable(accountUserMap.get(m.getAddManId())).map(AccountUser::getName).orElse("-"));
                m.setAddManPhone(Optional.ofNullable(accountUserMap.get(m.getAddManId())).map(AccountUser::getPhone).orElse("-"));
            });
        }
        return machineFaultLogs;
    }

    @Override
    public String selectUserReportedFaultsOrderNoByMachineId(Integer machineId) {
        return machineFaultLogDao.selectUserReportedFaultsOrderNoByMachineId(machineId);
    }

    @Override
    public List<MachineFaultLog> getUserCodePhone(Integer accountId, String userCode, String phone, String startTime, String endTime,
                                                  Integer rowCount, Integer pageNO) {

        Map<String, Object> map = new HashMap<>();
        if (userCode != null) {
            map.put("machineId", dataService.getMachineIdUserCode(userCode));
        }
        List<Integer> userIdDBs = new LinkedList<>();
        if (phone != null) {
            Integer brandId = accountService.getByAccount(accountId);
            User user = userService.getByPhone(brandId, phone);
            if (user != null) {
                userIdDBs.add(user.getUserId());
            }
            /**账号是否存在*/
            AccountUser accountUser = accountUserService.getByPhone(new AccountUser("86", phone, brandId));
            if (accountUser != null) {
                userIdDBs.add(accountUser.getAccountUserId());
            }

            if (userIdDBs == null || userIdDBs.isEmpty()) {
                throw new BaseException("AccountUser.notExist");
            }
        }

        map.put("addManid", StringUtil.getListString(userIdDBs));
        map.put("startTime", startTime);
        map.put("endTime", endTime);
        map.put("start", (pageNO - 1) * rowCount);
        map.put("rowCount", rowCount);
        List<MachineFaultLog> machineFaultLogs = machineFaultLogDao.getUserCodePhone(map);
        if (CollectionUtils.isNotEmpty(machineFaultLogs)) {
            List<Integer> dlsesPhone = machineFaultLogs.stream().filter(d -> d.getAddManName() == null).map(MachineFaultLog::getAddManId).collect(Collectors.toList());
            if (CollectionUtils.isNotEmpty(dlsesPhone)) {
                /**运维*/
                List<Integer> accountUserIds = machineFaultLogs.stream().filter(m -> m.getIntoMain().equals(0)).map(MachineFaultLog::getAddManId).collect(Collectors.toList());
                Map<Integer, AccountUser> accountUserMap = new HashMap<>();
                if (CollectionUtils.isNotEmpty(accountUserIds)) {
                    List<AccountUser> accountUsers = accountUserService.getByIds(accountUserIds);
                    for (AccountUser accountUser : accountUsers) {
                        accountUserMap.put(accountUser.getAccountUserId(), accountUser);
                    }
                }

                /**用户*/
                List<Integer> userIds = machineFaultLogs.stream().filter(m -> m.getIntoMain().equals(1)).map(MachineFaultLog::getAddManId).collect(Collectors.toList());
                Map<Integer, User> UserMap = new HashMap<>();
                if (userIds != null && !userIds.isEmpty()) {
                    List<User> Users = userService.getUserIds(userIds);
                    for (User accountUser : Users) {
                        UserMap.put(accountUser.getUserId(), accountUser);
                    }
                }

                machineFaultLogs.forEach(m -> {
                    if (accountUserMap.get(m.getAddManId()) != null) {
                        m.setAddManName(accountUserMap.get(m.getAddManId()).getName());
                        m.setAddManPhone(accountUserMap.get(m.getAddManId()).getPhone());
                    } else {
                        if (UserMap.get(m.getAddManId()) != null) {
                            m.setAddManName(UserMap.get(m.getAddManId()).getName());
                            m.setAddManPhone(UserMap.get(m.getAddManId()).getPhone());
                        }
                    }
                });
            }
            machineFaultLogs.forEach(m -> {
                if (Objects.equals(m.getIntoMain(), 0)) {
                    m.setFaults(FaultTypeConstant.matchFaultType(m.getFaults(), m.getFaultType()));
                }
            });
        }

        return machineFaultLogs;
    }
}
